package com.jzm.proxy;


import com.jzm.annotation.AutoWried;
import com.jzm.annotation.Transational;
import com.jzm.utils.DBUtils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;

public class DynamicServiceProxy implements InvocationHandler, Aop {
    private Connection connection = DBUtils.getConnection();

    private Object target;

    public DynamicServiceProxy(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //调用方法的返回对象、
        Object returnObject = null;

        try {
            before(target, method);
            //两个动作：实例化dao，，给dao里面的connetion对象赋值
            Class<?> aClass = this.target.getClass();
            Field[] declaredFields = aClass.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                AutoWried annotation = declaredField.getAnnotation(AutoWried.class);
                if (null != annotation) {
                    declaredField.setAccessible(true);
                    //DAO的class全名
                    Class<?> daoClass = Class.forName(declaredField.getType().getTypeName());
                    Object daoInstance = daoClass.newInstance();

                    //给dao里面connection赋值
                    Field[] daoFields = daoClass.getDeclaredFields();
                    for (Field daoField : daoFields) {
                        if (daoField.getType().getTypeName().equals(Connection.class.getTypeName())) {
                            daoField.setAccessible(true);
                            daoField.set(daoInstance, this.connection);
                            break;
                        }
                    }
                    //给service里面的dao实例对象赋值
                    declaredField.set(aClass.newInstance(), daoInstance);
                }
            }

            returnObject = method.invoke(target, args);

            after(target, method);
        } catch (Exception e) {
            error(target, method, e);
        }

        return returnObject;
    }

    @Override
    public void before(Object target, Method method) {
        //判断是否开启手工事务
        Transational annotation = method.getAnnotation(Transational.class);
        if (annotation != null) {
            //开启手动提交事务
            try {
                connection.setAutoCommit(false);
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }

    @Override
    public void after(Object target, Method method) {
        //判断是不是手动控制事务
        try {
            if (!connection.getAutoCommit()) {
                connection.commit();
            }
        } catch (Exception e) {
            error(target, method, e);
        }
    }

    @Override
    public void error(Object target, Method method, Throwable throwable) {
        //回滚事务
        try {
            connection.rollback();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }


    //获取代理类实例
    public <T> T getProxy() {
        return (T) Proxy.newProxyInstance(this.target.getClass().getClassLoader(), this.target.getClass().getInterfaces(), this);
    }

}
